package com.suarte.webapp.action;

import com.suarte.core.Employee;
import com.suarte.core.EmployeeType;
import com.suarte.core.service.EmployeeManager;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import org.appfuse.Constants;
import org.appfuse.model.Role;
import org.appfuse.model.User;
import org.appfuse.service.RoleManager;
import org.appfuse.service.UserExistsException;
import org.appfuse.util.ConvertUtil;

import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import javax.servlet.http.HttpServletResponse;
import org.appfuse.service.GenericManager;
import javax.servlet.http.HttpServletRequest;

/**
 * @date   Feb 21, 2010
 * @author Ggutierrez
 */
public class EmployeeForm extends BasePage implements Serializable {

    private static final long serialVersionUID = -1141119853856863204L;
    private EmployeeManager employeeManager;
    private GenericManager<EmployeeType, Long> employeeTypeManager;
    private Employee employee = new Employee();
    private RoleManager roleManager;
    private Map<String, String> availableRoles;
    private String[] userRoles;
    private User user = new User();
    private Long id;

    public void setEmployeeManager(EmployeeManager employeeManager) {
        this.employeeManager = employeeManager;
    }

    public void setEmployeeTypeManager(GenericManager<EmployeeType, Long> employeeTypeManager) {
        this.employeeTypeManager = employeeTypeManager;
    }

    public void setRoleManager(RoleManager roleManager) {
        this.roleManager = roleManager;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Employee getEmployee() {
        return employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public String delete() {
        employeeManager.remove(employee.getId());
        addMessage("employee.deleted");

        return "list";
    }

    public String edit() {
        HttpServletRequest request = getRequest();
        
        if (id != null) {
            log.debug("Editing employee, id is: " + id);
            employee = employeeManager.get(id);
            user = employee.getUser();
        } else {
            user = userManager.getUserByUsername(request.getRemoteUser());
            log.debug("Editing employee, username is: " + user.getUsername());
            employee = employeeManager.get(user.getUsername());
            if (employee == null){
                return "false";
            } else {
                log.debug("Editing employee, Name is: " + employee.getFirstName());
            }            
        }

        if (user.getUsername() != null) {
            user.setConfirmPassword(user.getPassword());
            if (isRememberMe()) {
                // if user logged in with remember me, display a warning that they can't change passwords
                log.debug("checking for remember me login...");
                log.trace("User '" + user.getUsername() + "' logged in with cookie");
                addMessage("userProfile.cookieLogin");
            }
        }

        if (user != null && user.getUsername() != null) {
            user.setConfirmPassword(user.getPassword());
            if (isRememberMe()) {
                // if user logged in with remember me, display a warning that they can't change passwords
                log.debug("checking for remember me login...");
                log.trace("User '" + user.getUsername() + "' logged in with cookie");
                addMessage("userProfile.cookieLogin");
            }
        }

        return "editProfile";
    }

    public String add() {
        employee = new Employee();
        user = new User();
        user.setEnabled(true);
        user.addRole(new Role(Constants.USER_ROLE));

        return "add";
    }

    public String save() throws IOException{
        boolean isNew = (employee.getId() == null);

        setUserRoles(getRequest().getParameterValues("employeeForm:userRoles"));

        Integer originalVersion = user.getVersion();
        
        if (user != null && user.getUsername() != null && user.getPassword() != null) {
            user.setFirstName(employee.getFirstName());
            user.setLastName(employee.getLastName());
            user.setEmail(employee.getEmail());
            user.setWebsite("http://tomcat.apache.org");
            user.setEnabled(true);

            for (int i = 0; (userRoles != null) && (i < userRoles.length); i++) {
                String roleName = userRoles[i];
                user.addRole(roleManager.getRole(roleName));
            }
        }

        try {
            user = userManager.saveUser(user);
        } catch (AccessDeniedException ade) {
            // thrown by UserSecurityAdvice configured in aop:advisor userManagerSecurity
            log.warn(ade.getMessage());
            getResponse().sendError(HttpServletResponse.SC_FORBIDDEN);
            return null;
        } catch (UserExistsException e) {
            addError("errors.existing.user", new Object[] { user.getUsername(), user.getEmail() });

            // reset the version # to what was passed in
            user.setVersion(originalVersion);
            return "edit";
        }

        if (user != null) {
            employee.setUser(user);
            employeeManager.save(employee);
        }

        String key = (isNew) ? "employee.added" : "employee.updated";
        addMessage(key);

        if (isNew) {
            return "list";
        } else {
            return "edit";
        }
    }

    public boolean isRememberMe() {
        if (user != null && user.getId() == null) {
            return false; // check for add()
        }
        AuthenticationTrustResolver resolver = new AuthenticationTrustResolverImpl();
        SecurityContext ctx = SecurityContextHolder.getContext();

        if (ctx != null) {
            Authentication auth = ctx.getAuthentication();
            return resolver.isRememberMe(auth);
        }
        return false;
    }

    public List<Employee> getEmployees() {
        return employeeManager.getAll();
    }

    public String getFrom() {
        if ((id != null) || (getParameter("editUser:add") != null)
                || ("list".equals(getParameter("from")))) {
            return "list";
        }

        return "";
    }

    @SuppressWarnings("unchecked")
    public Map<String, String> getAvailableRoles() {
        if (availableRoles == null) {
            List roles = (List) getServletContext().getAttribute(Constants.AVAILABLE_ROLES);
            availableRoles = ConvertUtil.convertListToMap(roles);
        }

        return availableRoles;
    }

    public String[] getUserRoles() {
        userRoles = new String[user.getRoles().size()];

        int i = 0;

        if (userRoles.length > 0) {
            for (Role role : user.getRoles()) {
                userRoles[i] = role.getName();
                i++;
            }
        }

        return userRoles;
    }

    public void setUserRoles(String[] userRoles) {
        this.userRoles = userRoles;
    }

    public List<EmployeeType> getEmployeeTypes(){
        return employeeTypeManager.getAll();
    }
}
